Designing a Testable and Extensible Logger
For production systems, I generally prefer an ILogger interface injected through dependency injection rather than making the logger static. Static logging is simple but creates global state and makes unit testing, replacement, and contextual configuration harder. A Singleton can centralize state, but dependency injection normally gives better lifecycle control and testability. The actual logging implementation can internally manage shared resources such as a file sink or logging pipeline.
Prefer an interface plus dependency injection for application/business components.
Static logging is acceptable for very small applications but creates global coupling.
A Singleton may be appropriate for an infrastructure resource, but it should not be used merely to avoid dependency injection.
Logging should support structured data, correlation IDs, log levels, and centralized configuration in distributed systems.
Unit tests can inject a fake logger without changing business logic.